#include "sock.hpp"
#include "util.hpp"
#include <time.h>
#include <vector>
#include <unordered_map>
#include <utility>
#include <algorithm> 
#include <functional>
class selectserver{
    using func_t = std::function<std::string(std::string)>;
public:
    selectserver(const uint16_t port,func_t buildingresponse) :_port(port),_listensock(-1),func(buildingresponse)
    {}
    void init(){
        _listensock = Sock::GetListenSock();
        Sock::Setsockopt(_listensock); //需要在bind之前设置
        Sock::Bind(_listensock,_port);
        Sock::Listen(_listensock,5);
        
        sockfds.push_back(_listensock);
    }
    void start(){
        for(;;){
            fd_set fds;
            FD_ZERO(&fds);
            fds_set(fds);
            // timeval timeout = {1,0};
            int maxfd = findmaxfd(sockfds);
            int ret = select(maxfd+1,&fds,nullptr,nullptr,nullptr);
            if(ret > 0){
                //等待成功
                logmessage(NORMAL,"wait is succuss");
                handler(fds);
            }else if(ret == 0){
                //超时
                logmessage(NORMAL,"wait is time_over");
            }else{
                logmessage(FATAL,"select faild");
                exit(SELECTERRO);
                //select调用失败
            }
    
        }

    }
    ~selectserver(){
        if(_listensock > -1 )   close(_listensock);
    }
private:
    int findmaxfd(std::vector<int>& fdsv){
        int ret = 0;
        for(auto& x : fdsv){
            ret = std::max(ret,x);
        }
        return ret;
    }
    void fds_set(fd_set& fds){
        std::cout<<"fd:";
        for(auto& x : sockfds){
            FD_SET(x,&fds);
            std::cout<<x<<" ";
        }
        std::cout<<std::endl;
    }
    void handler(fd_set& fds){
        //listen event
        if(FD_ISSET(_listensock,&fds)){
            if(sockfds.size() <= 1024){
                std::string ip;
                uint16_t port;
                int newsockfd = Sock::Accept(_listensock,&ip,&port);
                sockfds.push_back(newsockfd);
                logmessage(NORMAL,"%s:%d,new accept",ip.c_str(),port);
                infomation_list.insert(make_pair(newsockfd,make_pair(ip,port)));
            }else{
                logmessage(WARING,"accept faild,because list is voll,please wait");
            }
  
        }
        for(int x = 1 ; x < sockfds.size() ; x++){
            //read event
            if(FD_ISSET(sockfds[x],&fds)){
                logmessage(NORMAL,"wait succuss from%s,%d",infomation_list[sockfds[x]].first.c_str(),infomation_list[sockfds[x]].second);
                readhander(sockfds[x],x);
                
            }
        }

    }
    void readhander(const int fd,int pos){
        char buffer[1024];
        //这样读取是有问题的,因为无法读取到一个完整的报文!!!(需要自己订应用层协议),暂时这样读取
        memset(buffer,0,sizeof buffer);
        ssize_t r = read(fd,buffer,sizeof buffer);
        if(r > 0){
            buffer[r-1] = 0;
            std::cout<<"server ehco#"<<buffer<<std::endl;
        }else if(r == 0){
            close(fd);
            sockfds.erase(sockfds.begin() + pos);
            logmessage(NORMAL,"client quit");
            return;
        }else{
            close(fd);
            sockfds.erase(sockfds.begin() + pos);
            logmessage(ERROR,"read faild");
            return;
        }
        //构建response
        buffer[r-1] = '\n';
        std::string response = func(buffer);
        //write 下面的代码有问题,但是暂时不考虑
        write(fd,response.c_str(),response.size());
    }
private:
    uint16_t _port;
    int _listensock;
    std::vector<int> sockfds;
    std::unordered_map<int,std::pair<std::string,int>> infomation_list;
    func_t func;
};